package com.markor.tx.service.impl;

import com.markor.tx.bean.Family;
import com.markor.tx.mapper.FamilyMapper;
import com.markor.tx.service.FamilyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * @Author:zhangyanan
 * @Description:
 * @Date:Crated in 11:02 2018/3/14
 * @Modified By:
 */

/**
 * //@Transactional
 * 此注解可以作用于接口、接口方法、类以及类方法上。
 * 当作用于类时，该类的所有public方法将都具有该类型的事务属性，同时，我们可以在方法级别使用该注解来覆盖类级别的定义。
 *
 * ****注意：虽然@Transactional可以作用于接口、接口方法、类以及类方法上，但是spring建议不要再接口或者接口方法上使用该注解，
 * 因为这只有在使用基于接口的代理时它才会生效，该注解应该只被应用到public方法上，这是由Spring AOP本质决定的。
 * 如果你在protected、private或者默认可见性的方法上使用@Transactional注解，这将被忽略，也不会抛出任何异常。
 *
 *
 * spring事务原理大致为：springAOP 由CGLIB字节码方式生成代理Bean(Service)---->代理bean获取被代理bean的接口------>在执行方法目标service方法前开启事务---->执行被代理的service方法----->提交事务或者回滚事务
 * 详细请看Spring AOP原理
 *
 * 本案例虽然配置了mybatis，但是没有使用Mybatis mapper方法，因为serviceImpl方法名上不写@Transactional属于没有事务的概念，所以执行一句会提交一句，有兴趣的可以试一下
 */
@Service
public class FamilyServiceImpl implements FamilyService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * TransactionDefinition.PROPAGATION_REQUIRED
     * 如果当前存在事务，则加入该事务；如果当前没有事务，则创建一个新的事务，这是默认值。
     *
     * @param family
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void insertByRequired(Family family) {
        jdbcTemplate.update("insert into MK_FAMILY (PERSON_NUM) values (?)", family.getPersonNum());
    }

    /**
     * TransactionDefinition.PROPAGATION_REQUIRES_NEW
     * 创建一个新的事务，如果当前存在事务，则把当前事务挂起。
     *
     * @param family
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void insertByRequiresNew(Family family) {
        jdbcTemplate.update("insert into MK_FAMILY (PERSON_NUM) values (?)", family.getPersonNum());
    }

    /**
     * TransactionDefinition.PROPAGATION_SUPPORTS
     * 如果当前存在事务，则加入该事务；如果当前没有事务，则以非事务的方式继续运行。
     *
     * @param family
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    public void insertBySupports(Family family) {
        jdbcTemplate.update("insert into MK_FAMILY (PERSON_NUM) values (?)", family.getPersonNum());
    }

    /**
     * TransactionDefinition.PROPAGATION_NOT_SUPPORTED
     * 以非事务方式运行，如果当前存在事务，则将当前事务挂起。
     *
     * @param family
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void insertByNotSupported(Family family) {
        jdbcTemplate.update("insert into MK_FAMILY (PERSON_NUM) values (?)", family.getPersonNum());
    }

    /**
     * TransactionDefinition.PROPAGATION_NEVER
     * 以非事务方式运行，如果当前存在事务，则抛出异常
     *
     * @param family
     */
    @Transactional(propagation = Propagation.NEVER)
    public void insertByNever(Family family) {
        jdbcTemplate.update("insert into MK_FAMILY (PERSON_NUM) values (?)", family.getPersonNum());
    }

    /**
     * TransactionDefinition.PROPAGATION_MANDATORY
     * 如果当前存在事务，则加入该事务；如果当前没有事务，则抛出异常
     * @param family
     */
    @Transactional(propagation = Propagation.MANDATORY)
    public void insertByMandatory(Family family) {
        jdbcTemplate.update("insert into MK_FAMILY (PERSON_NUM) values (?)", family.getPersonNum());
    }

    /**
     * TransactionDefinition.PROPAGATION_NESTED
     * 如果当前存在事务，则创建一个事务作为当前的事务的嵌套事务来运行；
     * 如果当前没有事务，则该取值等价于TransactionDefinition.PROPAGATION_REQUIED
     * @param family
     */
    @Transactional(propagation = Propagation.NESTED)
    public void insertByNested(Family family) {
        jdbcTemplate.update("insert into MK_FAMILY (PERSON_NUM) values (?)", family.getPersonNum());
    }
}
